package 使用日志;
/*
Logback的配置
1.logback的默认配置

如果配置文件 logback-test.xml 和 logback.xml 都不存在，那么 logback 默认地会调用BasicConfigurator ，创建一个最小化配置。最小化配置由一个关联到根 logger 的ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化。root logger 默认级别是 DEBUG。

logback在启动时，根据以下步骤寻找配置文件：①在classpath中寻找logback-test.xml文件→②如果找不到logback-test.xml，则在 classpath中寻找logback.groovy文件→③如
果找不到 logback.groovy，则在classpath中寻找logback.xml文件，如果上述的文件都找不到，则logback会使用JDK的SPI机制
查找 META-INF/services/ch.qos.logback.classic.spi.Configurator中的 logback 配置实现类，这个实现类必须实现Configuration接口，使用它的实现来进行配置
如果上述操作都不成功，logback 就会使用它自带的 BasicConfigurator 来配置，并将日志输出到console。


　1、Logback的配置文件：
Logback 配置文件的语法非常灵活。正因为灵活，所以无法用 DTD 或 XML schema 进行定义。尽管如此，可以这样描述配置文件的基本结构：以开头，后面有零个或多个元素，有零个或多个元素，有最多一个元素。
　2、Logback默认配置的步骤：
　　(1). 尝试在 classpath下查找文件logback-test.xml；
　　(2). 如果文件不存在，则查找文件logback.xml；
　　(3). 如果两个文件都不存在，logback用BasicConfigurator自动对自己进行配置，这会导致记录输出到控制台。

2.logback.xml常用配置详解

1.根节点<configuration>包含三个属性：   

   •scan:默认为true。作用：当设置为true时，如果配置文件发生改变，将会被重新加载。
   •scanPeriod：默认时间间隔为1分钟，默认单位是毫秒，当scan为true时，此属性生效。作用：检测配置文件是否有修改时间间隔。
   •debug：默认为false。作用：当此属性为true时，将打印出logback内部日志信息，实时查看logback运行状态。
　　例如：
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                   <!--其他配置省略--> 
           </configuration>

2.子节点<contextName>:用来设置上下文名称。
          每个logger都关联到logger上下文，默认上下文名称为default。
          可以使用<contextName>设置成其他名字，用于区分不同的应用程序的记录。一旦设置，不能修改。
          例如：
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                  <contextName>myAppName</contextName>
                  <!--其他配置省略-->
　        </configuration>

3.子节点<property>:用来定义变量值，有两个属性name和value。
          通过<property>定义的值被插入到logger上下文中，可以使"${}"来使用变量。
          name:变量的名字
          value：变量名字对应的数值
          例如:
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                  <property name="APP_Name" value="myAppName"></property>
                  <contextName>${APP_Name}</contextName>
                  <!--其他配置省略-->
          </configuration>

 4.子节点<timestamp>:获取时间戳字符串，有两个属性key和datePattern。
          key：标识此<timestamp>的名字
          datePattern：设置将当前时间（即解析配置文件的时间）转换为字符串，遵循java.txt.SimpleDateFormat的格式。
             例如：
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"></timestamp>
                <contextName>${bySecond}</contextName>
           </configuration>

 5.子节点<appender>:负责写日志的组件，有两个必要属性name和class。
         name：指定appender名称
         class：指定appender的全限定名

5.1 class="ch.qos.logback.core.ConsoleAppender"：把日志输出到控制台，有以下子节点。
          <encoder>:对日志进行格式化。（具体参数稍后讲~~~~~~~~~~~~~） 
          <target>：字符串System.out（默认）或者System.err
            例如：
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                       <encoder>
                            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
                       </encoder>
               </appender>
               <root level="DEBUG">
                     <appender-ref ref="STDOUT"></appender-ref>
               </root>
         </configuration>	
         上述配置表示把>=DEBUG级别的日志都输出到控制台

 5.2 class="ch.qos.logback.core.FileAppender"：把日志添加到文件，有以下子节点：
          <file>：被写入的文件名，可以是相对目录，也可以是绝对目录，如果上级目录不存在会自动创建，没有默认值。
          <append>：默认为true。如果是true，日志被追加到文件结尾，如果是false，清空现存文件。
          <encoder>：对记录事件进行格式化。（具体参数稍后讲~~~~~~~~~~~）
          <prudent>：默认为false。如果是true，日志会被安全的写入文件，即其他的FileAppender也在向此文件做写入操作，效率低。
            例如：
           <configuration scan="true" scanPeriod="60 seconds" debug="false">
                  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
                         <file>testFile.log</file>
                         <append>true</append>
                         <encoder>
                                <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
                         </encoder>
                 </appender>
                <root level="DEBUG">
                     <appender-ref ref="FILE"/>
                </root>
           </configuration>
           上述配置表示把>=DEBUG级别的日志都输出到testFile.log


 5.3 class="ch.qos.logback.core.rolling.RollingFileAppender"：滚动记录文件，先将日志文件指定到文件，当符合某个条件时，将日志记录到其他文件。有以下子节点：
   <file>：被写入的文件名，可以是相对目录，也可以是绝对目录，如果上级目录不存在会自动创建，没有默认值。

　　<append>：默认为true。如果是 true，日志被追加到文件结尾，如果是 false，清空现存文件。

　　<rollingPolicy>：当发生滚动时，决定RollingFileAppender的行为，涉及文件移动和重命名。属性class定义具体的滚动策略类。　　

　　<triggeringPolicy >: 告知 RollingFileAppender 合适激活滚动。

　　<encoder>：对记录事件进行格式化。负责两件事：1）是把日志信息转换成字节数组，2）是把字节数组写入到输出流。

　　PatternLayoutEncoder 是唯一有用的且默认的encoder。有一个节点：

　　<pattern>节点，用来设置日志的输入格式。使用“%”加“转换符”方式，如果要输出“%”，则必须用“\”对“\%”进行转义。

 		class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"： 最常用的滚动策略，它根据时间来制定滚动策略，既负责滚动也负责出发滚动。有以下子节点：
            <fileNamePattern>：必要节点，包含文件名及"%d"转换符，"%d"可以包含一个java.text.SimpleDateFormat指定的时间格式，默认格式是 yyyy-MM-dd。也
                              可以设置其他格式，如：%d{yyyy-MM}。
            <maxHistory>:可选节点，控制保留的归档文件的最大数量，超出数量就删除旧文件。假设设置每个月滚动，且<maxHistory>是6，则只保存最近6个月的文件，删除之前的旧文件。
                         注:删除旧文件时，那些为了归档而创建的目录也会被删除。
			   注：（RollingFileAppender的<file>子节点可有可无，通过设置<file>，可以为活动文件和归档文件指定不同位置，当前日志总是记录到file指定的文件（活动文件），活动
			   文件的名字不会改变； 如果没设置file，活动文件的名字会根据fileNamePattern 的值，每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。）
           
      class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"： 查看当前活动文件的大小，如果超过指定大小会告知RollingFileAppender 触发
          	 当前活动文件滚动。只有一个节点:
　　　       <maxFileSize>:活动文件的大小，默认值是10MB。
　　　  <prudent>：当为true时，不支持FixedWindowRollingPolicy，支持TimeBasedRollingPolicy。但是有两个限制：
                 1）不支持也不允许文件压缩，2）不能设置file属性，必须留空。	
　　　  


　    class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy" ：根据固定窗口算法重命名文件的滚动策略。有以下子节点：
　　      <minIndex>:窗口索引最小值
　　      <maxIndex>:窗口索引最大值，当用户指定的窗口过大时，会自动将窗口设置为12。
　　      <fileNamePattern>:必须包含“%i”例如，假设最小值和最大值分别为1和2，命名模式为 mylog%i.log,会产生归档文件mylog1.log和mylog2.log。还可以指定文件
                           压缩选项，例如，mylog%i.log.gz 或者 没有log%i.log.zip
　　例如：	
　　<configuration scan="true" scanPeriod="60 seconds" debug="false">
　　　　<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
　　　　　　<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
　　　　　　　　<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
　　　　　　　　<maxHistory>30</maxHistory>
　　　　　　</rollingPolicy>
　　　　　　<encoder>
　　　　　　　　<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
　　　　　　</encoder>
　　　　</appender>
　　　　<root level="DEBUG">
　　　　　　<appender-ref ref="FILE"/>
　　　　</root>
　　</configuration>
      上述配置表示每天生成一个日志文件，保存30天的日志文件。

　　<configuration scan="true" scanPeriod="60 seconds" debug="false">

　　　　<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
　　　　　　<file>test.log</file>

　　　　　　<roollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
　　　　　　　　<fileNamePattern>tests.%i.log.zip</fileNamePattern>
　　　　　　　　<minIndex>1</minIndex>
　　　　　　　　<maxIndex>3</maxIndex>
　　　　　　</roollingPolicy>

　　　　　　<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
　　　　　　　　<maxFileSize>5MB</maxFileSize>
　　　　　　</triggeringPolicy>

　　　　　　<encoder>
　　　　　　　　<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
　　　　　　</encoder>
　　　　</appender>

　　　　<root level="DEBUG">
　　　　　<appender-ref ref="FILE" />
　　　　</root>
　　</configuration>
     上述配置表示按照固定窗口模式生成日志文件，当文件大于20MB时，生成新的日志文件。窗口大小是1到3，当保存了3个归档文件后，将覆盖最早的日志。


 5.4 还有SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender，并不常用，这里就不详解了。

6. 子节点<logger>：用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>。
        <logger>仅有一个name属性，一个可选的level和一个可选的addtivity属性。可以包含零个或多个<appender-ref>元素，标识这个appender将会添加到这个logger。

　　 name: 用来指定受此logger约束的某一个包或者具体的某一个类。
　　 level: 用来设置打印级别，大小写无关：TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF，还有一个特俗值INHERITED或者同义词NULL，代表强制执行上级的级别。 如果未设置此属性，那么当前logger将会继承上级的级别。
　　 addtivity: 是否向上级logger传递打印信息。默认是true。同<logger>一样，可以包含零个或多个<appender-ref>元素，标识这个appender将会添加到这个logger。

<!--为某个包单独配置logger

    比如定时任务，写代码的包名为：com.seentao.task
    步骤如下：
    1、定义一个appender，取名为task（随意，只要下面logger引用就行了）
    appender的配置按照需要即可

    2、定义一个logger:
    <logger name="com.seentao.task" level="DEBUG" additivity="false">
      <appender-ref ref="task" />
    </logger>
    注意：additivity必须设置为false，这样只会交给task这个appender，否则其他appender也会打印com.seentao.task里的log信息。

    3、这样，在com.seentao.task的logger就会是上面定义的logger了。
    private static Logger logger = LoggerFactory.getLogger(Class1.class);
-->

logger，负责定义我们实际代码中使用的logger。logger中有一个非常重要的属性name，name必须指定。在logback中，logger有继承关系，而所有的logger的祖先是root。
举个例子，如果我们有个类叫UserService，所在的包为com.maxwell.service，在UserService中要打印日志，我们一般会这么写：

①private Logger logger = LoggerFactory.getLogger(UserService.class);
或者
②private Logger logger = LoggerFactory.getLogger("com.maxwell.service.UserService");
这两种写法是一样的，第①中写法实际会转化为②中的方式来获取一个logger实例。
当我们写下这行代码时，logback会依次检查以下各个logger实例的是否存在，如果不存在则依次创建：

com
com.maxwell
com.maxwell.service
com.maxwell.service.UserService
而创建logger实例的时候，就会去配置文件中查找名字为com、com.maxwell、com.maxwell.service、com.maxwell.service.UserService的logge标签，并根据其中定义的规
则创建。所以，假如你在配置文件中没有定义name为上述字符串的logger时，就会找到root这个祖先，根据root标签定义的规则创建logger实例。

理解了上面的这一点，想要实现某个包或者某个类单独输出到某日志文件的需求就很好实现了：①定义一个appender，指明日志文件的输出目的地；②定义一个logger，name设为那个包或类的全
路径名。如果只想将这个类或包的日志输出到刚才定义的appender中，就将additivity设置为false。


7. 子节点<root>：它也是<logger>元素，但是它是根logger,是所有<logger>的上级。只有一个level属性，因为name已经被命名为"root",且已经是最上级了。有一个属性：
　　  level: 用来设置打印级别，大小写无关：TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF，不能设置为INHERITED或者同义词NULL。 默认是DEBUG。	
*/